home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / cpp_libs / varia / grammar1.lha / c++grammar1.1 / grammar4.txt < prev    next >
Text File  |  1990-06-07  |  69KB  |  1,635 lines

  1. Copyright (C) 1989.1990, James  A.   Roskind,  All  rights  reserved. 
  2. Abstracting  with credit is permitted.  The contents of this file may 
  3. be reproduced electronically, or in printed  form,  IN  ITS  ENTIRETY 
  4. with  no  changes, providing that this copyright notice is intact and 
  5. applicable in the copy.  No other copying is  permitted  without  the 
  6. expressed written consent of the author.
  7.  
  8. FILENAME: GRAMMAR4.TXT
  9. AUTHOR: Jim Roskind
  10.         Independent Consultant
  11.         516 Latania Palm Drive
  12.         Indialantic FL 32903
  13.         (407)729-4348
  14.         jar@ileaf.com
  15.         or ...!uunet!leafusa!jar
  16.  
  17.  
  18.     A YACC-able C++ 2.0 GRAMMAR, AND THE RESULTING AMBIGUITIES
  19.                                         (Release 1.1 Updated 6/90)
  20.  
  21. ABSTRACT
  22.  
  23. This  paper describes ambiguous aspects of the C++ language that have 
  24. been exposed by the construction of a YACC-able grammar for C++.  The 
  25. grammar  is  provided  in  a  separate  file, but there are extensive 
  26. references to the actual grammar.  In light of the fact that not  all 
  27. readers  will have access to a YACC capable of processing my grammar, 
  28. I have also included (in an appendix) a significant excerpt from  the 
  29. verbose output of running YACC on my grammar.
  30.  
  31. This  release  of  the grammars is provided to add some final touches 
  32. identified by the many users that picked up my  original  posting  in 
  33. 3/90.   As with my first posting, nested types have been omitted from 
  34. this release of the grammar.   The  decision  to  incorporate  nested 
  35. types into the C++ language was only clarified with AT&T's release of 
  36. version 2.1 of C++.  Since the addition of nested  types  appears  to 
  37. notably  complicate  the  interaction required between the parser and 
  38. the lexer, it seemed appropriate to release an update to the  grammar 
  39. that  tries  to  correct  all  known  deficiencies  found in my first 
  40. release.  A future release should incorporate all enhancements needed 
  41. for nested types.
  42.  
  43. Theoretical  Note  (skip if you hate theory): My C++ grammar does not 
  44. make use of the %prec or %assoc features of YACC, and hence conflicts 
  45. are  never hidden within my grammar.  The wondrous result is that, to 
  46. the extent to which my grammar can be seen to span the syntax of  the 
  47. language,  in all places where YACC reports no conflicts, the grammar 
  48. is a totally unambiguous statement of the  syntax  of  the  language.  
  49. This  result  is  remarkable (I think), because the "general case" of 
  50. deciding whether a grammar is ambiguous or not, is equivalent to (the 
  51. unsolvable) halting problem.
  52.  
  53. Although  this  paper  is  terse,  and  perhaps  poorly  (or at least 
  54. hastily) formed, I believe that its content is so significant  to  my 
  55. results  that  it  had to be included.  I am sorry that I do not have 
  56. the time at this point to better arrange its contents.
  57.  
  58.  
  59. CONTENTS
  60.         
  61.         INTRODUCTION
  62.         REVIEW: STANDARD LEXICAL ANALYSIS HACK: TYPEDEFname VS IDENTIFIER
  63.         STATUS OF MY "DISAMBIGUATED" GRAMMAR
  64.         18 EASY CONFLICTS, WITH HAPPY ENDINGS
  65.         2 REDUCTION CONFLICTS WITH STRAIGHT FORWARD DISAMBIGUATION
  66.         3 NOVEL CONFLICT THAT YIELD TO SEMANTIC DISAMBIGUATION
  67.         THE TOUGH AMBIGUITIES: FUNCTION LIKE CASTS AND COMPANY
  68.         SAMPLE RESOLUTIONS OF AMBIGUITIES BY MY C++ GRAMMAR
  69.         DIFFICULT AMBIGUITIES FOR C++ 2.0 PARSER TO TRY
  70.         COMMENTARY ON CURRENT C++ DISAMBIGUATING RULES
  71.         SOURCE OF CONFLICTS IN C++ (MIXING TYPES AND EXPRESSIONS)
  72.         FUNCTION LIKE CAST vs DECLARATION : THE TOUGH EXAMPLE
  73.         CONCLUSION
  74.  
  75.         APPENDIX A:
  76.             PROPOSED GRAMMAR MODIFICATIONS (fixing '*', '&' and ':'
  77.                                         conflicts)
  78.         APPENDIX B:
  79.             AMBIGUITIES IN MY C++ GRAMMAR AS LISTED BY YACC VERBOSE OPTION
  80.  
  81.  
  82.         APPENDIX C:
  83.             ADVANCED TUTORIAL ON YACC CONFLICTS
  84.  
  85. INTRODUCTION
  86.  
  87. This paper is intended  to  go  into  significant  detail  about  the 
  88. ambiguities  that I have seen in the C++ 2.0 language, and exposed by 
  89. attempting to develop a YACC compatible (i.e., LALR(1))  grammar.   I 
  90. must point out that this is NOT meant as an attack on the language or 
  91. the originators thereof, but rather an  R&D  effort  to  disambiguate 
  92. some  details.  (I  personally  believe that Stroustrup et.  al.  are 
  93. doing a GREAT job).  I have the vague hope that the extensive hacking 
  94. that  I  have done with YACC on the C++ grammar has given me a rather 
  95. novel vantage point. (I have  expressed  my  observations  to  Bjarne 
  96. Stroustrup,  and  in  doing  so  verified  that  other  folks had not 
  97. previously  identified  several  of  my  points).   In  light  of  my 
  98. activities,  this  paper  includes a fair amount of philosophizing. I 
  99. hope that none of this paper assumes too greatly that I have  insight 
  100. that  is  beyond  that  of  the readers, and certainly no insults are 
  101. intended.
  102.  
  103. If you like investigating grammars directly (rather than reading what 
  104. I  have to say), I would strongly suggest you read the ANSI C grammar 
  105. before looking at the C++ grammar.  The C++ grammar is pretty  large, 
  106. and  you can expect the following stats if you have a similar YACC to 
  107. that I am using:
  108.  
  109. Berkeley YACC (1.4 2/25/90):
  110.  
  111. 25 shift/reduce conflicts, 7 reduce/reduce conflicts.
  112. 103 terminals, 161 nonterminals
  113. 609 grammar rules, 1157 states
  114.  
  115.  
  116. AT&T YACC (with large table sizes):
  117.  
  118. 123/127 terminals, 160/200 nonterminals
  119. 609/650 grammar rules, 1157/1200 states
  120. 25 shift/reduce, 7 reduce/reduce conflicts reported
  121. 243/350 working sets used
  122. memory: states,etc. 13727/60000, parser 10871/12000
  123. 495/600 distinct lookahead sets
  124. 756 extra closures
  125. 7300 shift entries, 25 exceptions
  126. 1797 goto entries
  127. 4731 entries saved by goto default
  128. Optimizer space used: input 18036/60000, output 8092/12000
  129. 8092 table entries, 3568 zero
  130. maximum spread: 351, maximum offset: 1148
  131.  
  132.  
  133.  
  134. REVIEW: STANDARD LEXICAL ANALYSIS HACK: TYPEDEFname VS IDENTIFIER
  135.  
  136. This section is targeted  at  readers  that  are  not  familiar  with 
  137. parsing  C  with a context free grammar.  The reader should note that 
  138. there are two distinct forms of `identifiers' gathered during lexical 
  139. analysis,  and  identified as terminal tokens in both of my grammars.  
  140. The  terminal  tokens   are   called   IDENTIFIER   and   TYPEDEFname 
  141. respectively. This distinction is a required by a fundamental element 
  142. of the C language.  The definition of a  "TYPEDEFname"  is  a  lexeme 
  143. that  looks  like  a standard identifier, but is currently defined in 
  144. the symbol table as being declared a typedef (or class, struct,  enum 
  145. tag)  name. All other lexemes that appear as identifiers (and are not 
  146. keywords) are  tokenized  as  IDENTIFIERs.   The  remainder  of  this 
  147. section will review the motivation for this approach.
  148.  
  149. Consider the following sample code, which uses the C language:
  150.  
  151.         ...
  152.         int main() { f (*a) [4] ; ...
  153.  
  154. Most  reader  will intuitively parse the above sequence as a function 
  155. call to "f", with an argument "*a", the  return  value  of  which  is 
  156. (probably)  a  pointer,  and  hence  can  be indexed by "4".  Such an 
  157. interpretation presumes that the prior context was something like:
  158.  
  159.         ...
  160.         extern float *a;
  161.         char * f(float);
  162.         int main() { f (*a) [4] ; ...
  163.  
  164. However, if the prior context was **INSTEAD**:
  165.  
  166.         ...
  167.         typedef int f;
  168.         extern float a;
  169.         int main() { f (*a) [4] ; ...
  170.  
  171. then the interpretation of  the  code  is  entirely  different.   The 
  172. fragment  in  question actually redeclares a local variable "a", such 
  173. that the type of "a" is "pointer to array of 4 int's"!  So we see  in 
  174. this   example  that  the  statement  "f(*a)[4];"  cannot  be  parsed 
  175. independent of context.
  176.  
  177. The standard solution to the above ambiguity is to allow the  lexical 
  178. analyser  to  form  different tokens based on contextual information. 
  179. The contextual  information  that  is  used  is  the  answer  to  the 
  180. question:  "Is a given identifier defined as a typedef name (or class 
  181. name) at the current point in the  parse"?   I  will  refer  to  this 
  182. feedback  loop  (from  the parser that stores information in a symbol 
  183. table, wherein the lexer extracts the information) as the "lex hack".  
  184. With  this  lex  hack in place the code fragment "f(*a)[4];" would be 
  185. provided by the lexer as either:
  186.  
  187.         IDENTIFIER '(' '*' IDENTIFIER ')' '[' INTEGERconstant ']' ';'
  188.  
  189. or
  190.  
  191.         TYPEDEFname '(' '*' IDENTIFIER ')' '[' INTEGERconstant ']' ';'
  192.  
  193. The two case are very easy for a context free grammar to distinguish, 
  194. and  the  ambiguity vanishes.  Note that the fact that such a hack is 
  195. used (out of necessity) demonstrates that C is  not  a  context  free 
  196. language,  but the hack allows us to continue to use an LR(1) parser, 
  197. and a context free grammar.
  198.  
  199. Note that this hack is, of necessity, also made use  of  in  the  C++ 
  200. grammar,  but no additional feedback (a.k.a.: hack) is required.  The 
  201. interested reader should also  note  that  this  feedback  loop  (re: 
  202. updating  the  symbol  table)  must be swift, as the lexical analyser 
  203. cannot proceed very far without this  contextual  information.   This 
  204. constraint  on  the  feedback  time  often  prevents  the parser from 
  205. "deferring" actions, and hence increases the pressure on  the  parser 
  206. to rapidly disambiguate token sequences.
  207.  
  208. (Although  this  version  of  the C++ grammar does not support nested 
  209. types, the advanced reader is encouraged to consider their impact  on 
  210. the  above problem.  Specifically, code fragments such as "T::f" must 
  211. syntactically distinguish themselves as either typenames, or members.  
  212. Problems in this area can be expected to stress the above hack almost 
  213. to its breaking point.   The  resolution  to  this  problem  will  be 
  214. discussed in the next release of the grammar,... so stay tuned.).
  215.  
  216.  
  217. STATUS OF MY "DISAMBIGUATED" GRAMMAR
  218.  
  219. My  grammar  is  now  fairly  complete.  Several independent reviews, 
  220. which provided a front end lexical analyser and parsed  existing  C++ 
  221. code,  have  verified  that  the  grammars  span  of the C++ language 
  222. appears complete.  I  have  not  incorporated  parametric  types  nor 
  223. exception  handling into the grammars at this point, as they continue 
  224. to be in a state of flux.
  225.  
  226. The grammar does (I believe) support all the features provided in C++ 
  227. 2.0,  including  multiple inheritance and the enhanced operator "new" 
  228. syntax (includes placement expression). I believe  that,  except  for 
  229. the  minor  change  involving  not  permitting parentheses around bit 
  230. field names during a declaration, my C++ grammar supports a  superset 
  231. of  my  ANSI  C  grammar. Note that I haven't inline expanded all the 
  232. rules in the C grammar that were required for C++ disambiguation (re: 
  233. deferring  reductions),  and  hence a `diff' of the two grammars will 
  234. not provide a trivial comparison.  The resulting major  advantage  of 
  235. this  grammar over every other current C++ parser (that I know of) is 
  236. that it supports old style function definitions AS WELL  AS  all  the 
  237. standard  C++.   (It  is  my  personal  belief  that such support was 
  238. dropped by many compilers and translators in  order  to  resolve  the 
  239. many  syntax problems that appear within C++.  I believe this grammar 
  240. shows that such a decision was premature).
  241.  
  242. My list of shift-reduce and reduce-reduce conflicts is currently:  25 
  243. shift/reduce,  7  reduce/reduce conflicts reported.  I have chosen to 
  244. leave so many conflicts in the grammar because I hope to see  changes 
  245. to the syntax that will remove them, rather than making changes to my 
  246. grammar that will firmly accept and disambiguate  them.  (Considering 
  247. the  detailed  analysis  presented  here, such changes would only add 
  248. unnecessary complications to the grammar).
  249.  
  250. 8 SR caused by operator function name with trailing * or &
  251. 8 SR caused by freestore              with trailing * or &
  252. 1 SR caused by operator function name OR freestore, with trailing :
  253. 1 SR caused by dangling else and my laziness
  254.  
  255. 1 SR and 1 RR caused by operator function name and trailing {
  256.  
  257. 3 SR caused by constructor declaration vs member declaration
  258.  
  259. 3 RR caused by function-like cast vs identifier declaration ambiguity
  260. 3 RR caused by function-like cast vs typedef redeclaration ambiguity
  261. 3 SR caused by redundant parened TYPEDEFname redeclaration vs old style cast
  262.  
  263.  
  264. Of these conflicts, the ones that most C++ parser authors are  mainly 
  265. concerned    with   are   the   last   9   conflicts,   relating   to 
  266. function-like-cast vs declaration, and redundant parened  TYPEDEFname 
  267. redeclaration  vs  old  style  cast.   The  following sections breeze 
  268. through the "easy" conflicts, and then talk at  length  about  the  9 
  269. tough ones.
  270.  
  271.  
  272. 18 EASY CONFLICTS, WITH HAPPY ENDINGS
  273.  
  274. The first group of 18 SR conflicts:
  275.  
  276. 8 SR caused by operator function name with trailing * or &
  277. 8 SR caused by freestore              with trailing * or &
  278. 1 SR caused by operator function name OR freestore, with trailing :
  279. 1 SR caused by dangling else and my laziness
  280.  
  281. have very simple resolutions.  If you are reading this, I assume that 
  282. you are already familiar with the if-if-else conflict.
  283.  
  284. The trailing ':' has to do with the use of the  colon  in  a  ternary 
  285. "... ? ... : ..." expression.  The easiest example is:
  286.  
  287.         void * p = boolean ? new struct S : ...
  288.  
  289. The  problem  is  that this MIGHT be the first mention of "struct S", 
  290. and this MIGHT be where the elaboration of the structure is provided!  
  291. Under  such circumstances, what follows the ':' MIGHT be a base class 
  292. name, and the entire curly braced elaboration for S (ugh!).
  293.  
  294. My resolution of this SR conflict is that "the longest possible  type 
  295. is constructed by the parser".  Hence the ':' is construed to be part 
  296. of the type "struct S".  This is in keeping with the subtle statement 
  297. on  in  section  7.1 of the C++ 2.0 Ref Man: "The longest sequence of 
  298. decl-specifier that could possibly be a type name  is  taken  as  the 
  299. decl-specifiers of a declaration".
  300.  
  301.  
  302. The  8 conflicts based "freestore with trailing * or &" can be hinted 
  303. at by the example:
  304.  
  305.         a = new int * * object;
  306.  
  307. Is the above the same as:
  308.  
  309.         a = (new int) * (* T);
  310. or:
  311.         a = (new (int *)) * T;
  312.  
  313. Again the "longest possible type" is isolated  by  my  grammar.   The 
  314. result is:
  315.  
  316.         a = (new (int * * )) ...
  317.  
  318. which  leads  to  a  syntax  error in my example!  This resolution is 
  319. indeed what is quietly specified for  C++  2.0  (and  implemented  in 
  320. cfront).   The  critical statement and example in the C++ 2.0 Ref Man 
  321. at the end of section 5.3.3 makes this resolution clear.
  322.  
  323. The 8 conflicts involving "operator function names with trailing * or 
  324. &"  are  quite similar to what was just presented.  The critical fact 
  325. is that "operator typename" is allowed in the  grammar  to  define  a 
  326. function.   Whenever  a  function  is provided, but NOT followed by a 
  327. '(', the address of the function is implicitly taken and used in  the 
  328. expression  (see  draft ANSI C standard for finer details).  For some 
  329. class T, the following MIGHT all be valid statements:
  330.  
  331.         operator T;
  332.         operator T*;
  333.         operator T**;
  334.  
  335. If the above are valid, then the interpretation of the  following  is 
  336. ambiguous:
  337.  
  338.         operator T * * a;
  339.  
  340. The above might be interpreted as:
  341.  
  342.         (operator T) * (* a);
  343. or
  344.         (operator (T *)) * a;
  345.  
  346. The default LR rules parse the largest possible type, and lead to:
  347.  
  348.         (operator (T * * )) ...
  349.  
  350. which  in  our  example  leads  to  a  syntax  error.  Here again the 
  351. "longest possible type..." rule supports my grammar.  Note that  this 
  352. rule  is  actually  a  consequence  (in  my  opinion)  of  the cfront 
  353. implementation via a YACC grammar,  and  the  default  resolution  of 
  354. conflicts in that grammar.
  355.  
  356.  
  357. 2 REDUCTION CONFLICTS WITH STRAIGHT FORWARD DISAMBIGUATION
  358.  
  359. The two conflicts that were described as:
  360.  
  361.    1 SR and 1 RR caused by operator function name and trailing {
  362.  
  363. occur  when  there is an ambiguity as to whether the '{' is the start 
  364. of a function body in a  function  definition,  or  the  start  of  a 
  365. structure/class/enum  elaboration.  In part, this ambiguity is caused 
  366. by the fact that an  arbitrary  declarator  is  used  in  a  function 
  367. definition,  but  semantics require the declarator in a definition to 
  368. have  type  "function  returning  ...".   This  subtlety  causes  the 
  369. following  to  be  a  syntactically  valid  function definition, even 
  370. though it is semantically invalid:
  371.  
  372.         void func { int a; } ...
  373.  
  374. Semantic requirements on the declarator demand something more like:
  375.  
  376.         void func() { int a; }  ...
  377.  
  378. By using "operator struct S" in place of "func" in the first  example 
  379. we get:
  380.  
  381.         void operator struct S { int a; } ...
  382.  
  383. My  C++  grammar  attempts to assemble the longest possible type, and 
  384. hence parses this example as equivalent to:
  385.  
  386.         void operator (struct S { int a;} ) ...
  387.  
  388. Interestingly enough, this resolution not only supports the  "longest 
  389. possible type" rule, but also avoids the semantically invalid parse.
  390.  
  391.  
  392. 3 NOVEL CONFLICTS THAT YIELD TO SEMANTIC DISAMBIGUATION
  393.  
  394. The  conflicts  that are discussed in this section have been deferred 
  395. (by A LOT of work, and A LOT of inline expansion) to occur when a ';' 
  396. is  reached.   At  that point, semantic information in the tokens can 
  397. safely be used to decide which of two cases are at hand.
  398.  
  399. The conflicts referred to as:
  400.  
  401.     3 SR caused by constructor declaration vs member declaration
  402.  
  403. occur during a  class/struct  elaboration.   Consider  the  following 
  404. class elaborations:
  405.  
  406.         typedef int T1, T2, T3  ;
  407.         class GOO { int a;} ;
  408.         class FOO {
  409.                 GOO    T1  ; // clearly a redefinition of T1
  410.                 FOO  ( T2 ); // clearly a constructor
  411.                 GOO  ( T3 ); // redefinition of T3
  412.                 };
  413.  
  414. Note  that  the  last two entries in FOO's elaboration "FOO(T2);" and 
  415. "GOO(T3);" are tokenized  IDENTICALLY,  but  must  have  dramatically 
  416. different  meanings.  When I first found this ambiguity I was hopeful 
  417. that I could extend the lex hack that distinguishes TYPEDEFnames from 
  418. random  IDENTIFIERs, and distinguish something like CURRENTCLASSname. 
  419. Unfortunately, the potential  for  elaborations  within  elaborations 
  420. appears  to  make such a hack unworkable.  In addition, once I got my 
  421. grammar to defer all such ambiguous cases until a  ';'  was  seen,  I 
  422. felt  confident that the ambiguity was resolved (and the introduction 
  423. of an additional "hack" was unnecessary).
  424.  
  425.  
  426. THE TOUGH AMBIGUITIES: FUNCTION LIKE CASTS AND COMPANY
  427.  
  428. The ambiguities  listed  in  this  section  pertain  to  attempts  to 
  429. distinguish  declaration/types-names  from  expressions  names.   For 
  430. example:
  431.  
  432.     char *b ="external" ; // declare a variable to confuse us :-)
  433.     main () {
  434.         class S;
  435.         S (*b)[5]; // redeclare "b" pointer to array of 5 S's ?
  436.                // OR ELSE indirect through b; cast to S; index using 5 ?
  437.         }
  438.  
  439. The above is what I call  the  "declaration  vs  function  like  cast 
  440. ambiguity".   Awareness  about this ambiguity in this context appears 
  441. fairly widespread among C++ parser authors.   The  C++  2.0  Ref  Man 
  442. makes  explicit  reference  to this problem in section 6.8 "Ambiguity 
  443. Resolution".  I believe the underlying  philosophy  provided  by  the 
  444. Reference  Manual  is that if a token stream can be interpreted by an 
  445. ANSI C compiler to be a  declaration,  then  a  C++  compiler  should 
  446. disambiguate  in  favor of a declaration.  Unfortunately, section 6.8 
  447. goes on to say:
  448.  
  449.     "To disambiguate, the whole statement may have to be examined  to 
  450.     determine  if  it  is  an expression-statement, or a declaration.  
  451.     ... The disambiguation is purely syntactic; that is, the  meaning 
  452.     of  the  names, beyond whether they are type-names or not, is not 
  453.     used in the disambiguation".
  454.  
  455. The above  advice  only  forestalls  the  inevitable  ambiguity,  and 
  456. complicates  the  language  in the process.  The examples that follow 
  457. will demonstrate the difficulties.
  458.  
  459. There are several other contexts where such ambiguities  (typedef  vs 
  460. expression) arise:
  461.  
  462.         1) Where a statement is valid (as shown above).
  463.         2) As the argument to sizeof()
  464.         3) Following "new", with the C++ syntax allowing a placement
  465.                 expression
  466.         4) Immediately following a left paren  in  an  expression  (it 
  467.                 might be an old style cast, and hence a type name)
  468.         5)  Following  a  left paren, arguments to constructors can be 
  469.                 confused with prototype type-names.
  470.         6) Recursively in any of the above,  following  a  left  paren 
  471.                 (what  follows might be argument expressions, or might 
  472.                 be function prototype parameter typing)
  473.  
  474. Examples of simple versions of the sizeof context are:
  475.  
  476.         class T;
  477.         sizeof ( T    ); // sizeof (type-name)
  478.         sizeof ( T[5] ); // again a type name
  479.         sizeof ( T(5) ); // sizeof (expression)
  480.         sizeof ( T()  ); // semantic error: sizeof "function returning T"?
  481.                         // OR ELSE sizeof result of function like cast
  482.  
  483. Examples  of  the  old  style cast ambiguity context, which are still 
  484. ambiguous when the '(' after the 'T' has been seen:
  485.  
  486.         class T { /* put required declarations here */ 
  487.                 };
  488.         a = (T(      5));  // function like cast of 5
  489.         b = (T(      )) 0; // semantic error: cast of 0 to type "function
  490.                         // returning T"
  491.  
  492. In constructors the following demonstrates the problems:
  493.  
  494.         class T;
  495.         T (b)(int  d ); // same as "T b(int);", a function declaration
  496.         T (d)(int (5)); // same as "T d(5);", an identifier declaration
  497.         T (d)(int ( )); // ambiguous
  498.  
  499. The problem can appear recursively in  the  following  examples.   By 
  500. "recursively"  I  mean that an ambiguity in the left-context has left 
  501. the parser unsure of whether an "expression" or  a  "type"  is  being 
  502. parsed,  and the ambiguity is continued by the token sequence.  After 
  503. the parser can determine what this subsequence is, it will in turn be 
  504. able to disambiguating what the prior tokens were.
  505.  
  506. Recursion on the statement/declaration context:
  507.  
  508.         class S;
  509.         class T;
  510.         S (*b)(T); // declare b "pointer to function taking T returning S"
  511.         S (*c)(T dummy); // same declaration as for "b"
  512.         int dummy;
  513.         S (*d)(T (dummy)); // This T might be casting dummy
  514.  
  515. Recursion  on  the sizeof context is shown in the following examples. 
  516. As before, the examples include semantic errors.
  517.  
  518.         class T;
  519.         class S;
  520.         sizeof ( T(S dummy) ); // sizeof "function taking S returning T"
  521.         int dummy;
  522.         sizeof ( T(S (dummy)) ); // sizeof "function taking S returning T"
  523.                 // OR ELSE cast dummy to S, and then cast that to T, which
  524.                         // is the same as "sizeof T;"
  525.  
  526.  
  527. The following are the precise conflicts, along with typical contexts.  
  528. I  have derived the contexts by manually walking backwards through my 
  529. verbose  YACC  output.   Note  that  I  have  deleted  some  of   the 
  530. insignificant  rules  from  the  verbose  state  descriptions in this 
  531. section  (insignificant  in  that  they  are  not  involved  in   the 
  532. conflict).   To  see  the complete details of each conflict state see 
  533. the appendix at the end of this paper.
  534.  
  535.  
  536. WARNING: THE REMAINDER OF THIS SECTION IS  VERY  DETAILED  AND  TERSE 
  537. (PERHAPS  EVEN  CRYPTIC);  DO NOT TRY TO READ IT CAREFULLY UNLESS YOU 
  538. HAVE A LOT OF TIME TO KILL, AND A LOT OF  INTEREST  IN  THE  GRAMMAR.  
  539. (You  can skip to the next section, which is a bit less technical and 
  540. terse).
  541.  
  542. ---------------------------------------------------------------------
  543.         Minimal left context:   "main() { int ( identifier"
  544.                 Is the identifier being declared?
  545.                 Is the identifier a function name?
  546.                 Is the identifier an array name?
  547.                    (The last two cases use function like casting into 
  548.                    type "int")
  549.  
  550.         Left context can include an arbitrary number of '*', '&',  or 
  551.                 '('  immediately  to the left of the identifier.  The 
  552.                 basic.type.name    "int"    can    also    be     any 
  553.                 simple.type.name (e.g., a TYPEDEFname)
  554.  
  555.         My Default is to become a declarator, which then forms a 
  556.         declaration
  557.  
  558. 642: reduce/reduce conflict (red'ns 17 and 22 ) on (
  559. 642: reduce/reduce conflict (red'ns 17 and 22 ) on )
  560. 642: reduce/reduce conflict (red'ns 17 and 22 ) on [
  561. state 642
  562.         paren.identifier.declarator :  rescoped.identifier_    (17)
  563.         primary.expression :  rescoped.identifier_    (22)
  564.  
  565. ---------------------------------------------------------------------
  566.         Required left context:   "... ( TYPEDEFname ()",
  567.             where "..." includes a type.specifier.
  568.             It is assumed that "function returning TYPEDEFname"
  569.                 is a valid "type.name".  Semantically this is
  570.                 rarely legal, but the focus is on syntax here.
  571.  
  572.             The above sequence could eventually parse into:
  573.             ... ( declarator             )
  574.             ... ( type.name              ) cast.expression
  575.             ... ( expression             )
  576.             ... ( parameter.decl.list    )
  577.             Note that parameter.decl.list is:
  578.                     type.name
  579.                     type.name = default.value , ...
  580.                     type.name , parameter.decl.list
  581.             Expanded examples are:
  582.                 sizeof ( expression )
  583.                 sizeof ( type.name  )
  584.                    where the argument to "sizeof" is one of the following:
  585.                 int ( typename2 ( TYPEDEFname() )
  586.                 int ( typename2 ( TYPEDEFname()  ,
  587.                 int ( typename2 ( TYPEDEFname() = expression
  588.                 int ( TYPEDEFname()
  589.             Is the TYPEDEFname a declaration specifier?
  590.             Is TYPEDEFname used as function like cast of 0 args?
  591.  
  592.         Left  context can include an arbitrary number of '*', '&', or 
  593.                 '(' immediately to the left  of  the "(TYPEDEFname".
  594.  
  595.         Default is to become a type.qualifier.list, 
  596.             which becomes the trailing section of a  parameter.type.list,
  597.             which becomes a function.returning.modifier for a declarator,
  598.             which forces a redeclaration of TYPEDEFname,
  599.              (semantics may outlaw this redeclaration of TYPEDEFname
  600.                 as a function WITHOUT use of "extern"!!!)
  601.  
  602. 740: reduce/reduce conflict (red'ns 74 and 64 ) on )
  603. 740: reduce/reduce conflict (red'ns 74 and 64 ) on ,
  604. 740: reduce/reduce conflict (red'ns 74 and 64 ) on =
  605. state 740
  606.         postfix.expression :  TYPEDEFname ( )_    (74)
  607.         parameter.type.list :  ( )_type.qualifier.list.opt
  608.         type.qualifier.list.opt : _    (64)
  609.  
  610. ---------------------------------------------------------------------
  611.         Minimal left context:   "main() { int ( ( TYPEDEFname"
  612.                 Is the TYPEDEFname being redeclared?
  613.                 Is TYPEDEFname in parenthesis the start as old style cast?
  614.  
  615.         Left context can include an arbitrary number of '*', '&',  or 
  616.                 '('  between the two '('s.  The basic.type.name "int" 
  617.                 can also be any simple.type.name (e.g., a TYPEDEFname)
  618.  
  619.         Default is to become a typedef.declarator,
  620.             which leads to the redeclaration of the TYPEDEFname
  621.  
  622. 782: shift/reduce conflict (shift 595, red'n 418) on )
  623. state 782
  624.         type.name :  TYPEDEFname_    (418)
  625.         simple.paren.typedef.declarator :  ( TYPEDEFname_)
  626.  
  627. ---------------------------------------------------------------------
  628.         Minimal left context:   "main() { int ( ( TYPEDEFname[2]"
  629.          OR
  630.         Minimal left context:   "main() { int ( ( TYPEDEFname(float)"
  631.                 Is the TYPEDEFname being redeclared?
  632.                 Is "array of TYPEDEFname" the type for
  633.                         an old style cast?  The result of the cast
  634.                         expression will undergo a function like cast into
  635.                         an int.
  636.  
  637.         Left context can include an arbitrary number of '*', '&',  or 
  638.                 '('  between the two '('s.  The basic.type.name "int" 
  639.                 can also be any simple.type.name (e.g., a TYPEDEFname)
  640.  
  641.         Default to form a typedef.declarator,
  642.                  which leads to a redeclaration of the  TYPEDEFname.
  643.                 (Semantics preclude cast to this type anyway, so we have
  644.                 actually syntactically disallowed a semantic error)
  645.  
  646. 874: shift/reduce conflict (shift 838, red'n 591) on )
  647. state 874
  648.         paren.postfix.typedef.declarator :  ( TYPEDEFname postfixing.abstract.declarator_)
  649.         abstract.declarator :  postfixing.abstract.declarator_    (591)
  650.  
  651. ---------------------------------------------------------------------
  652.         Minimal left context:   "main() { int ( * ( TYPEDEFname"
  653.                 Is the TYPEDEFname being redeclared?
  654.                 Is TYPEDEFname in parenthesis the start as old style
  655.                     cast? The result of the cast will undergo and 
  656.                     indirection, and the result of that will be 
  657.                     cast to int by a function like cast!
  658.  
  659.         Left context can include an arbitrary number of '*', '&',  or 
  660.                 '('  to the left of the '*'.  The basic.type.name "int" 
  661.                 can also be any simple.type.name (e.g., a TYPEDEFname)
  662.  
  663.         Default to form a typedef.declarator,
  664.                 which leads to a redeclaration of the  TYPEDEFname.
  665.  
  666. 875: shift/reduce conflict (shift 840, red'n 418) on )
  667. state 875
  668.         type.name :  TYPEDEFname_    (418)
  669.         paren.typedef.declarator :  indirect.or.reference ( TYPEDEFname_)
  670.  
  671. ---------------------------------------------------------------------
  672.  
  673.  
  674. SAMPLE RESOLUTIONS OF AMBIGUITIES BY MY C++ GRAMMAR
  675.  
  676.  
  677. Of the "hard examples" given in the C++ reference manual  (r6.8),  my 
  678. grammar  can  only "properly" detect a "statement-expression" for the 
  679. stream:
  680.  
  681.         T(a,5)>>c;
  682.  
  683. All the other examples default to  a  declarator  after  the  closing 
  684. parenthesis  following  the  identifier.   (See  my  comments  in the 
  685. conclusion section of this paper).
  686.  
  687. I actually am not sure I agree with all the examples in the  C++  2.0 
  688. Reference Manual. Specifically, the example in section 6.8:
  689.  
  690.         T (*d) (double(3));  // expression statement
  691.  
  692. In  the  example  "T"  is  specified  to be a simple-type-name, which 
  693. includes all the basic  types  as  well  as  class-names,  and  more. 
  694. Considering the following are valid declarations:
  695.  
  696.         void *a (0);
  697.         void *b (int(0));
  698.         void (*c)(int(0));
  699.  
  700. I am unable to see the "syntactic" difference between this last token 
  701. stream and the  example  just  cited  in  the  reference  manual.  My 
  702. simplistic  parser  gives  me  the result that I at least expect.  It 
  703. concludes (prematurely, but seemingly correctly) that the stream is a 
  704. declaration (with a new style initializer).
  705.  
  706. As  a  positive note, my grammar is able to parse the example given a 
  707. while back in comp.lang.c++, that Zortech 1.07 cannot parse:
  708.  
  709.         a = (double(a)/double(b))...;
  710.  
  711. Apparently,  upon  seeing  "(double"  some  parsers   commit   to   a 
  712. parenthesized  type-name for a cast expression, and cannot proceed to 
  713. parse a parenthesized expression.  No  mention  of  this  problem  is 
  714. listed in my conflict list, as resolution of this problem is simply a 
  715. matter of letting the LR parser wait long enough  before  committing.  
  716. Specifically, my grammar has not yet committed when all of:
  717.  
  718.         a = (double(a)
  719.  
  720. has  been  seen!   The  next  character  ('/')  allows the grammar to 
  721. unambiguously  conclude  that  the  sequence  "double(a)..."  is   an 
  722. expression.
  723.  
  724.  
  725. DIFFICULT AMBIGUITIES FOR A "C++ 2.0" COMPATIBLE PARSER TO TRY
  726.  
  727. Having  seen  the  above contexts, I would be curious to see if other 
  728. C++ front ends with "smart lexers" (such as cfront)  can  handle  the 
  729. following.   These  examples  are  not  guaranteed  to  be  evaluated 
  730. correctly by my grammar, but I expect them to demonstrate  weaknesses 
  731. in  many other parsers.  The interpretation of these examples per C++ 
  732. 2.0  definitions  requires  massive  lookahead.   In  addition,   the 
  733. examples  are  generally  unreadable by humans, and rarely parsed the 
  734. same way by any two implementations.
  735.  
  736.     main()
  737.       {
  738.       class T 
  739.         { 
  740.         /* ... */
  741.         } a;
  742.       typedef T T1,T2,T3,T4,T5,T7,T8,T9,Ta,Tb,Tc,Td;
  743.         { /* start inner scope */
  744.         T((T1)         ); // declaration
  745.         T((T2)    a    ); // Statement expression
  746.         T((T3)(       )); // declaration of T3
  747.         T((T4)(T      )); // declaration of T4
  748.         T((T5)(T  a   )); // declaration of T5
  749.         T((T6)(T((a) ))); // declaration of T6
  750.         T((T7)(T((T) ))); // declaration of T7
  751.         T((T8)(T((T)b))); // statement expression
  752.  
  753.         T(b[5]); // declaration
  754.         T(c());  // declaration
  755.         T(d()[5]);  // statement expression ? (function returning array 
  756.                       // is semantically illegal, but syntactically proper)
  757.         T(e[5]());  // statement expression ? (No array of functions)
  758.         T(f)[5]();  // statement expression ?  "                   "
  759.         
  760.         T(*Ta() )[5] [4];  //declaration
  761.         T(*Tb() [5]) [4];  //statement expression ? (function returning array)
  762.  
  763.         T(*Tc()) [3 +2];  //declaration
  764.         T(*Td()) [3 ]+2;  //statement expression
  765.  
  766.         }
  767.       }        
  768.  
  769.  
  770. COMMENTARY ON C++ 2.0 DISAMBIGUATING RULES
  771.  
  772. There are two distinct thrusts in conflict disambiguation as provided 
  773. by  AT&T's efforts to define a standard for C++.  The first thrust is 
  774. "parse tokens into the longest possible declarator, and identify  the 
  775. syntax  errors  that  result".   The second thrust is to "use massive 
  776. external technology ("smart lexer", a.k.a.: "recursive decent  parser 
  777. that  helps  the  lexer",  a.k.a.  LALEX)  to look ahead, so that the 
  778. parser doesn't mis-parse a function-like-cast as  a  declaration  and 
  779. induce  a  syntax  error".   The  first  is a commitment to LR parser 
  780. technology, and an existing grammar (which could be cleaned up).  The 
  781. second  is a commitment to NOT use an LR parser, and to the use of an 
  782. existing implementation.
  783.  
  784. It is my belief that LR parsers are well understood, and the addition 
  785. of  a  "smart  lexer" destroys all structure in a parser.  The result 
  786. can be anticipated to become a quagmire of code and hacks.  With this 
  787. firm  conviction,  I  have  provided  my  grammar in the hopes that a 
  788. standard can emerge that IS well defined, and is  implementable,  and 
  789. is readable by humans.
  790.  
  791.  
  792.  
  793. SOURCE OF CONFLICTS IN C++ (MIXING TYPES AND EXPRESSIONS)
  794.  
  795. One  fundamental strength in C is the similarity between declarations 
  796. and expressions.  The syntax of  the  two  is  intended  to  be  very 
  797. similar, and the result is a clean declaration and expression syntax. 
  798. (It takes some getting used to,  but  it  is  in  my  opinion  good).  
  799. Unfortunately,  there  are some slight distinctions between types and 
  800. expressions, which Ritchie et.  al.  apparently noticed.  It  is  for 
  801. this  reason  (I  am guessing) that the C cast operator REQUIRES that 
  802. the type be enclosed in parenthesis.  Moreover, there is also a clear 
  803. separator   in   a   declaration   between  the  declarator  and  the 
  804. initializing expression (the '=') (as some of you know, there is some 
  805. interesting  history  in  this area.).  The bottom line (as seen with 
  806. 20-20 hindsight) is: "keep declarations  and  expressions  separate".  
  807. Each violation of this basic rule has induced conflicts.
  808.  
  809.  
  810. To  be  concrete about the differences between types and expressions, 
  811. the following two distinctions are apparent:
  812.  
  813.     1) Abstract declarators are permitted.  No analogy is provided in 
  814.     expressions.    The   notable   distinction   is   that  abstract 
  815.     declarators include the possibility of trailing '*' tokens.
  816.         
  817.     2) The binding of elements in a  declaration  is  very  different 
  818.     from  any  expression.   Notably,  the declaration-specifiers are 
  819.     bound separately to each declarator in the comma  separated  list 
  820.     of  declarators  (example:  int  a, b, c;).  With (most forms of) 
  821.     expressions,  a  comma  provides  a   major   isolation   between 
  822.     expressions.
  823.  
  824. C  also  used  reserved  names  to  GREATLY  reduce the complexity of 
  825. parsing.  The introduction of typedef names increased the  complexity 
  826. (it  made  the language context sensitive), but a simple hack between 
  827. lex and YACC overcame the problem.  An example is the statement:
  828.  
  829.         name (*b)[4];
  830.  
  831. Note that this  is  ambiguous,  EVEN  in  ANSI  C,  IF  there  is  no 
  832. distinction  between type-names and function names!  (i.e., "b" could 
  833. be getting redeclared to be of type "pointer to array  of  name",  OR 
  834. the function "name" could be called with argument "*b", the result of 
  835. which is indexed to the 4th element). In C, the two  kinds  of  names 
  836. (TYPEDEFnames  and  function  names  (a.k.a.:  declared identifiers)) 
  837. share a name space, and at every point in a source program the (hack) 
  838. contextual  distinction can be made by the tokenizer.  Hacks are neat 
  839. things in that the less you use them, the more  likely  they  are  to 
  840. work  when  you  REALLY need them (i.e., you don't have to fight with 
  841. existing hacks).  Having worked on designing  and  implementing  a  C 
  842. compiler,  I  was  pleasantly  amazed  at how the constructs all fell 
  843. together.
  844.  
  845. The  major  violations  of  this  approach  (i.e.,  keep  declaration 
  846. separate from expressions) that come to mind with C++ are: 
  847.  
  848.         function-like-casts,
  849.         freestore expressions without parens around the type,
  850.         conversion function names using arbitrary type specifiers,
  851.         parenthesized initializers that drive constructors.
  852.  
  853. The  last  problem, parenthesized initializers, provides two areas of 
  854. conflicts.  The first is really an interference issue with old  style 
  855. C function definitions, which only bothers folks at file scope (GNU's 
  856. G++ compiler considered this to be too great an  obstacle,  and  they 
  857. don't  currently  support old style C definitions!).  The second part 
  858. of this conflict  involves  a  more  subtle  separation  between  the 
  859. declarator,  and  the  initializer. (K&R eventually provided an equal 
  860. sign as an unequivocal separator, but parens used in C++ are  already 
  861. TOO  overloaded to separate anything).  The significance of this lack 
  862. of a clear separator is that it  is  difficult  to  decide  that  the 
  863. "declarator"  is complete, and that the declared name should be added 
  864. to the scope.  The last problem does interact in a nasty way with the 
  865. function-like  cast  vs  declaration conflicts (the problem slows the 
  866. feedback loop to the symbol table, which  is  critical  to  continued 
  867. lexing).  The parened initializers also provide another context where 
  868. it is difficult to distinguish between expressions (a  true  argument 
  869. list for the constructor) and a declaration continuation (a parameter 
  870. type list).  
  871.  
  872. The second problem listed falls out of the "new-expression"  with  an 
  873. unparenthesized type.  This form of freestore (such as "new int * *") 
  874. allows types to be placed adjacent to expressions, and  the  trailing 
  875. '*'  ambiguity  rears  its head.  I can easily prove that this is the 
  876. culprit in terms of specific  ambiguities,  in  that  removing  these 
  877. (unnecessary?) forms significantly disambiguates the grammar.  (It is 
  878. rather nice to use YACC  as  a  tool  to  prove  that  a  grammar  is 
  879. unambiguous!).  It is interesting to note that if only the derivation 
  880. of a freestore expression were limited  to  (using  the  non-terminal 
  881. names of the form that the C++ Reference manual uses):
  882.  
  883.         new placement-opt ( type-name )  parened-arg-list-opt
  884.  
  885. then  all  the  LR(1)  reduce  conflicts  based on this problem would 
  886. vanish.  Indeed, the culprit can clearly be shown to be:
  887.  
  888.         new placement-opt  restricted-type-name parened-arg-list-opt
  889.  
  890. The characters which excite these reduction conflicts are  '*',  '&', 
  891. and ':'.  The context in which the ':' is significant occurs when the 
  892. freestore expression is the middle expression of the ternary operator 
  893. set  "?:".   In this ternary operator context, the use of a type name 
  894. such as "class a" leaves the LR(1) parser confused about the  meaning 
  895. of a ':' that follows.
  896.  
  897. The     third    problem    that    I    indicated    involves    the 
  898. conversion-function-name.  Here again, if the syntax were  restricted 
  899. to ONLY:
  900.  
  901.         operator simple-type-name
  902.  
  903. then  the  LR(1)  conflicts  would vanish.  It is interesting to note 
  904. that the keyword "operator" serves as the  left  separator,  and  the 
  905. restriction  to  "simple-type-name"  results  in  an  implicit  right 
  906. separator  (simple-type-names  are  exactly  one  token  long).   The 
  907. conflicts  appear  when multiple tokens are allowed for a declaration 
  908. specifier, and an optional pointer-modifier list may be  added  as  a 
  909. postfix.   The  conflicts  that  result  from this lack of separation 
  910. include  all  those  provided  by  the  freestore  example,  and   an 
  911. additional   set   as   well.    The  additional  conflicts  are  not 
  912. semantically significant, but  they  are  noticeable  to  a  compiler 
  913. writer.  The interesting new trailing character conflict is '{'.  The 
  914. context for this conflict involves the  definition  of  a  conversion 
  915. function,  which  always  includes  a  function  body (with a leading 
  916. character of '{' ).  A simple grammar does not SYNTACTICALLY  require 
  917. that      "function      returning      modifier"      follow     the 
  918. conversion-function-name in  all  declarations/definitions,  although 
  919. semantics  do  require such.  Hence an LR(1) conflict occurs when the 
  920. type-name is of  the  form  "struct  A",  and  a  possible  structure 
  921. elaboration may follow (with leading character '{' ).
  922.  
  923. Here  again (as with the unambiguous version of freestore) the syntax 
  924. could be extended to:
  925.  
  926. operator.function.name :
  927.         OPERATOR any.operator
  928.         | OPERATOR basic.type.name
  929.         | OPERATOR TYPEDEFname
  930.         | OPERATOR type.qualifier
  931.         | OPERATOR '(' type.name ')'
  932.         ;
  933.  
  934. instead of:
  935.  
  936. operator.function.name :
  937.         OPERATOR any.operator
  938.         | OPERATOR type.specifier.or.name  operator.function.ptr.opt
  939.         | OPERATOR type.qualifier.list     operator.function.ptr.opt
  940.         ;
  941.  
  942. and the ambiguities would vanish (and the expressivity would  not  be 
  943. diminished).
  944.  
  945.  
  946. FUNCTION LIKE CAST VS DECLARATION AMBIGUITIES
  947.  
  948. The real big culprit (i.e., my anti-favorite) in this whole ambiguity 
  949. set  (re:  keeping   types   and   expressions   separate)   is   the 
  950. function-like-cast.   The  reason  why it is so significant (to an LR 
  951. parser)  is  that  the  binding  of  a  type-name,  when  used  in  a 
  952. function-like-cast,   is  directly  to  the  following  parenthesized 
  953. argument list.  In contrast, the binding of a type-name when used  in 
  954. a  declaration  is  to  all  the  "stuff"  that  follows,  up until a 
  955. declarator termination mark like a ',', ';' or '='. Life really  gets 
  956. tough  for LR folks when the parse tree MUST be reduced, but you just 
  957. can't tell how yet.  With this problem, the  hacks  began  to  appear 
  958. (re:  the  "smart  lexer").  Note that these new style casts are much 
  959. more than a notational convenience  in  C++.  The  necessity  of  the 
  960. function like cast lies in the fact that such a cast can take several 
  961. arguments, whereas the old style cast is ALWAYS a unary operator.
  962.  
  963. I was (past tense) actually working towards  resolving  this  problem 
  964. via some standard methods that I have developed (re: inline expansion 
  965. of rules to provide deferred reduction).  I  was  (past  tense)  also 
  966. using one more sneaky piece of work to defer the reductions, as I was 
  967. carefully making use of right recursion (instead of the standard left 
  968. recursion)  in  order  to  give  the parser a chance to build up more 
  969. context.   I  can  demonstrate  the  usefulness  of  right  recursive 
  970. grammars  in disambiguating difficult toy grammars.  Unfortunately, I 
  971. realized at some point that I NEEDED to perform certain actions (such 
  972. as  add  identifiers  to  the  symbol table) in order to complete the 
  973. parse!?!  This was my catch 22.  I could POSSIBLY parse using an LALR 
  974. grammar,  if I could only defer actions until I had enough context to 
  975. disambiguate.  Unfortunately, I HAD to perform certain  actions  (re: 
  976. modify  the  symbol table, which changed the action of the tokenizer) 
  977. BEFORE I could continue to examine tokens!  In some  terrible  sense, 
  978. the typedef hack had come back to haunt me.
  979.  
  980. I backed off a bit in my grammar after reaching this wall, and now my 
  981. grammar only waits until it reaches the identifier in  the  would  be 
  982. declarator.   I  really  didn't  want  to  parse  the stuff after the 
  983. identifier name (sour grapes?), because  I  knew  I  would  not  (for 
  984. example)  be  able  to  identify  a "constant expression" in an array 
  985. subscript (most of the time, if it isn't constant, then it can't be a 
  986. declaration).   I  don't  believe that a compiler should compete in a 
  987. battle of wits with  the  programmer,  and  the  parser  was  already 
  988. beginning  to outwit me (i.e., I was having a hard time parsing stuff 
  989. mentally that is provided as examples in the 2.0 Reference Manual).   
  990.  
  991.  
  992. FUNCTION LIKE CAST vs DECLARATION : THE TOUGH EXAMPLE:        
  993.         
  994. The following is about the nastiest example that I have been able  to 
  995. construct  for this ambiguity group.  I am presenting it here just in 
  996. case someone is left with a thought that there is "an easy way out".
  997.  
  998. The  fact  that  identifiers  can  remain  ambiguous  SO  LONG  after 
  999. encountering  them  can  cause  no end of trouble to the parser.  The 
  1000. following example does not succumb to static (re: no  change  to  the 
  1001. symbol  table)  anticipatory  lexing  of  a  statement.   As such, it 
  1002. demonstrates the futility of attempting to use  a  "smart  lexer"  to 
  1003. support  the  philosophy: "If it can be interpreted as a declaration, 
  1004. then so be it;  otherwise  it  is  an  expression".   This  ambiguous 
  1005. example  exploits  the  fact  that  declarators  MUST be added to the 
  1006. symbol table as soon as  they  are  complete  (and  hence  they  mask 
  1007. external declarations).
  1008.  
  1009. First I will present the example without comments:
  1010.  
  1011. class Type1 {
  1012.             Type1 operator()(int);
  1013.             } ;
  1014. class wasType2 { ...}; 
  1015. int (*c2)(Type1 dummy);
  1016.  
  1017. main ()
  1018.     {
  1019.     const int    a1  = 0, new_var  (4), (*c1)(int     (a1));
  1020.     Type1       (a2) = 3, wasType2 (4), (*c2)(wasType2(a1));
  1021.     }
  1022.  
  1023.  
  1024.  
  1025.  
  1026. Now to repeat the example with comments:
  1027.  
  1028. class Type1 {....
  1029.             Type1 operator()(int);
  1030.             } ;
  1031. class wasType2 { ....}; /* we will almost redeclare this typename!?! */
  1032. int (*c2)(Type1 dummy); /* we will NOT redeclare Type1 */
  1033.  
  1034. main ()
  1035.     {
  1036.     /* The first line is indeed simple.  It is simply placed here
  1037.     to hint at how the second line MIGHT analogously be parsed. */
  1038.     
  1039.     const int    a1  = 0, new_var  (4), (*c1)(int     (a1));
  1040.  
  1041.     /*  As  a review, "a1" is declared to be a constant with value 0. 
  1042.         "new_var" is declared to be another constant, but with  value 
  1043.         4.  Finally,  "c1"  is  declared  to  be a pointer to a const 
  1044.         integer, and the initial value of this pointer is  "int(a1)", 
  1045.         which  is  the  same  as "int(0)", or simply "0" (a.k.a., the 
  1046.         null pointer). It is significant that "a1" entered the symbol 
  1047.         table  quickly  so  that  it  could  be  used  later  in  the 
  1048.         declaration. */
  1049.  
  1050.     /* Static lexing of what follows will suggest that the  following 
  1051.     is  also  a  declaration.   This  statement  is  actually 3 comma 
  1052.     separated expressions!! The explanation that follows  shows  that 
  1053.     assuming   the   2nd  statement  is  a  declaration  leads  to  a 
  1054.     contradiction. */
  1055.     
  1056.     Type1      (a2) = 3, wasType2 (4), (*c2)(wasType2(a1));
  1057.     
  1058.     /* Assume this second statement is a declaration.  Note  that  by 
  1059.     the  time  "c2" is parsed, "wasType2" has been redeclared to be a 
  1060.     variable of type "Type1".  Hence  "wasType2(a1)"  is  actually  a 
  1061.     function  call  to  "wasType2.operator()(a1)",  and  it  is not a 
  1062.     function    prototype    arg    list.     It     follows     that 
  1063.     "(*c2)(wasType2(a1))"  is  an  expression,  and NOT a declarator!  
  1064.     Since this last entry is not a declarator, the  entire  statement 
  1065.     must  be an expression (ugh! it is time to backtrack). After much 
  1066.     work on my part, I think it might even be  a  semantically  valid 
  1067.     expression.   Once this backtracking is complete, we see that the 
  1068.     first expression "Type1 (a2) = 3" is  an  assignment  to  a  cast 
  1069.     expression.  The second expression "wasType2 (4)", is a cast of a 
  1070.     constant.  The  third  expression  "(*c2)(wasType2(a1))",  is  an 
  1071.     indirect  function  call.  The argument of the call is the result 
  1072.     of a cast.  Note that "wasType2" is  actually  never  redeclared, 
  1073.     but it was close! */
  1074.     
  1075.     /*  For  those of you who can parse this stuff in your sleep, and 
  1076.     noticed the slight error  in  the  above  argument,  I  have  the 
  1077.     following "fix".  The error is that the 
  1078.  
  1079.         "(*c2)(wasType2(a1))" 
  1080.  
  1081.     could actually be a declaration with a parenthesized initializer.  
  1082.     I could have change this token subsequence to:
  1083.  
  1084.         "(*(*c2)(wasType2(a1)))(int(a1))"
  1085.  
  1086.     and avoid the constructor ambiguity, but it would only complicate 
  1087.     the  discussion.   Note that in this form, if "wasType2" is not a 
  1088.     type, the the quoted text cannot be a declaration.*/
  1089.  
  1090.     /* Two parens are all a user would need to  add  to  the  cryptic 
  1091.     example  to  unambiguously  specify  that  this  statement  is an 
  1092.     expression.  Specifically: */
  1093.     
  1094.        (Type1) (a2) = 3, wasType2 (4), (*c2)(wasType2(a1));
  1095.     /* or ...*/
  1096.        (Type1 (a2) = 3), wasType2 (4), (*c2)(wasType2(a1));
  1097.  
  1098.     /* I would vote for a syntax error in such ambiguous stream, with 
  1099.     an  early  decision that it was a declaration.  After seeing this 
  1100.     example, I doubt that I could quickly assert that I could produce 
  1101.     a non-backtracking parser that disambiguates statements according 
  1102.     to the C++ 2.0 rule.  I am sure  I  can  forget  about  a  simple 
  1103.     lex-YACC combination doing it. */
  1104.  
  1105.     }
  1106.  
  1107.  
  1108. Most  simply  put,  if  a  "smart  lexer"  understands these: a) I am 
  1109. impressed, b) Why use a parser when a lexer can parse so well?
  1110.  
  1111. The bottom line is that disambiguation of declarations via "If it can 
  1112. be  a  declaration,  then it is one", seems to require a backtracking 
  1113. parser. (Or some very fancy parsing approach).  I am not even sure if 
  1114. the above examples are as bad as it can get!
  1115.  
  1116.  
  1117. CONCLUSION
  1118.  
  1119. I  believe that the C++ grammar that I have made available represents 
  1120. a viable machine readable standard for the syntax description of  the 
  1121. C++  language.   In  cases where the ambiguities are still exposed by 
  1122. conflicts (as noted by YACC), to further defer  resolution  would  be 
  1123. detrimental  to  a  user.   I see no benefit in describing a computer 
  1124. language that must support human writers, but cannot be understood by 
  1125. humans.    Any   code  that  exploits  such  deferral  is  inherently 
  1126. non-portable, and deserves to be diagnosed as an  error  (my  grammar 
  1127. asserts  a  "syntax  error").   Rather than dragging the C++ language 
  1128. into support for a ad-hoc parser implementations such as cfront  (and 
  1129. the "smart lexer"), I would heavily suggest the use of my grammar.  I 
  1130. do not believe that my grammar would "break" much existing code,  but 
  1131. in cases where it would, the code would not be portable anyway (other 
  1132. than to a port of an IDENTICAL parser).
  1133.  
  1134. I hope to see a great deal of use of my grammars, and I believe  that 
  1135. standardizing  on  the represented syntax will unify the C++ language 
  1136. greatly.
  1137.  
  1138.         Jim Roskind
  1139.         Independent Consultant
  1140.         516 Latania Palm Drive
  1141.         Indialantic FL 32903
  1142.         (407)729-4348
  1143.         ...uunet!leafusa!jar
  1144.  
  1145.  
  1146. APPENDIX A:
  1147.   PROPOSED GRAMMAR MODIFICATIONS (fixing '*', '&' and ':' conflicts)
  1148.  
  1149. Based on the other  items  described  above,  I  have  the  following 
  1150. suggestions  for  cleaning up the grammar definition.  Unfortunately, 
  1151. it provides subtle variations from the "C++ 2.0" standard.
  1152.  
  1153.  
  1154. Current Grammar:
  1155.  
  1156. operator.function.name :
  1157.         OPERATOR any.operator
  1158.         | OPERATOR type.specifier.or.name  operator.function.ptr.opt
  1159.         | OPERATOR type.qualifier.list     operator.function.ptr.opt
  1160.         ;
  1161.  
  1162.  
  1163. operator.new.type:
  1164.         type.qualifier.list      operator.new.declarator.opt
  1165.                         operator.new.initializer.opt
  1166.         | type.specifier.or.name operator.new.declarator.opt
  1167.                         operator.new.initializer.opt
  1168.         ;
  1169.  
  1170. Proposed new grammar (which requires parens around complex types):
  1171.  
  1172. operator.function.name :
  1173.         OPERATOR any.operator
  1174.         | OPERATOR basic.type.name
  1175.         | OPERATOR TYPEDEFname
  1176.         | OPERATOR type.qualifier
  1177.         | OPERATOR '(' type.name ')'
  1178.         ;
  1179.  
  1180. operator.new.type:
  1181.         basic.type.name    operator.new.initializer.opt 
  1182.         | TYPEDEFname      operator.new.initializer.opt 
  1183.         | type.qualifier   operator.new.initializer.opt 
  1184.         | '(' type.name ') operator.new.initializer.opt 
  1185.         ;
  1186.  
  1187. The impact of the above changes is that all complex type names (i.e.: 
  1188. names that are not simply a typedef/class name, or a basic type names 
  1189. like char) must be enclosed in parenthesis  in  both  `new  ...'  and 
  1190. `operator  ...' expressions. Both of the above changes would clear up 
  1191. a number of ambiguities.  In some sense, the current "disambiguation" 
  1192. (of  trailing  '*', '&', and ':') is really a statement that whatever 
  1193. an LR(1) parser cannot disambiguate is a syntax error.  In  contrast, 
  1194. the above rules define an unambiguous grammar.
  1195.  
  1196.  
  1197. APPENDIX B:
  1198.   AMBIGUITIES IN MY C++ GRAMMAR AS LISTED BY YACC VERBOSE OPTION
  1199.  
  1200. The  following  are  the  list of conflicts that were reported in the 
  1201. verbose output from an AT&T compatible YACC.  I have only listed  the 
  1202. conflict states here, as the entire file is well in excess of 500K.
  1203.  
  1204.  
  1205. 182: shift/reduce conflict (shift 183, red'n 286) on :
  1206. 182: reduce/reduce conflict (red'ns 286 and 280 ) on {
  1207. state 182
  1208.         aggregate.name :  aggregate.key identifier.or.typedef.name_derivation.opt $$284 { member.declaration.list.opt }
  1209.         aggregate.name :  aggregate.key identifier.or.typedef.name_    (286)
  1210.         derivation.opt : _    (280)
  1211.  
  1212.         :  shift 183
  1213.         {  reduce 280
  1214.         .  reduce 286
  1215.  
  1216.         derivation.opt  goto 415
  1217.  
  1218.  
  1219. 187: shift/reduce conflict (shift 427, red'n 369) on {
  1220. state 187
  1221.         enum.name :  ENUM identifier.or.typedef.name_{ enumerator.list }
  1222.         enum.name :  ENUM identifier.or.typedef.name_    (369)
  1223.  
  1224.         {  shift 427
  1225.         .  reduce 369
  1226.  
  1227.  
  1228. 189: shift/reduce conflict (shift 50, red'n 29) on *
  1229. 189: shift/reduce conflict (shift 51, red'n 29) on &
  1230. state 189
  1231.         operator.function.name :  OPERATOR type.specifier.or.name_operator.function.ptr.opt
  1232.         operator.function.ptr.opt : _    (29)
  1233.  
  1234.         TYPEDEFname  shift 431
  1235.         *  shift 50
  1236.         &  shift 51
  1237.         .  reduce 29
  1238.  
  1239.         operator.function.ptr.opt  goto 428
  1240.         pointer.operator  goto 429
  1241.         indirect.or.reference  goto 430
  1242.  
  1243.  
  1244. 190: shift/reduce conflict (shift 50, red'n 29) on *
  1245. 190: shift/reduce conflict (shift 51, red'n 29) on &
  1246. state 190
  1247.         operator.function.name :  OPERATOR type.qualifier.list_operator.function.ptr.opt
  1248.         type.qualifier.list :  type.qualifier.list_type.qualifier
  1249.         basic.type.specifier :  type.qualifier.list_basic.type.name
  1250.         sue.type.specifier :  type.qualifier.list_elaborated.type.name
  1251.         typedef.type.specifier :  type.qualifier.list_TYPEDEFname
  1252.         operator.function.ptr.opt : _    (29)
  1253.  
  1254.         DOUBLE  shift 42
  1255.         INT  shift 39
  1256.         STRUCT  shift 68
  1257.         LONG  shift 40
  1258.         ENUM  shift 66
  1259.         CHAR  shift 37
  1260.         UNION  shift 69
  1261.         CONST  shift 63
  1262.         FLOAT  shift 41
  1263.         SHORT  shift 38
  1264.         UNSIGNED  shift 44
  1265.         SIGNED  shift 43
  1266.         VOID  shift 36
  1267.         VOLATILE  shift 64
  1268.         CLASS  shift 70
  1269.         TYPEDEFname  shift 433
  1270.         *  shift 50
  1271.         &  shift 51
  1272.         .  reduce 29
  1273.  
  1274.         operator.function.ptr.opt  goto 432
  1275.         pointer.operator  goto 429
  1276.         indirect.or.reference  goto 430
  1277.         basic.type.name  goto 151
  1278.         type.qualifier  goto 150
  1279.         elaborated.type.name  goto 152
  1280.         aggregate.name  goto 48
  1281.         enum.name  goto 49
  1282.         aggregate.key  goto 65
  1283.  
  1284.  
  1285. 429: shift/reduce conflict (shift 50, red'n 29) on *
  1286. 429: shift/reduce conflict (shift 51, red'n 29) on &
  1287. state 429
  1288.         operator.function.ptr.opt :  pointer.operator_operator.function.ptr.opt
  1289.         operator.function.ptr.opt : _    (29)
  1290.  
  1291.         TYPEDEFname  shift 431
  1292.         *  shift 50
  1293.         &  shift 51
  1294.         .  reduce 29
  1295.  
  1296.         operator.function.ptr.opt  goto 636
  1297.         pointer.operator  goto 429
  1298.         indirect.or.reference  goto 430
  1299.  
  1300.  
  1301. 430: shift/reduce conflict (shift 50, red'n 29) on *
  1302. 430: shift/reduce conflict (shift 51, red'n 29) on &
  1303. state 430
  1304.         operator.function.ptr.opt :  indirect.or.reference_operator.function.ptr.opt
  1305.         pointer.operator :  indirect.or.reference_type.qualifier.list
  1306.         operator.function.ptr.opt : _    (29)
  1307.  
  1308.         CONST  shift 63
  1309.         VOLATILE  shift 64
  1310.         TYPEDEFname  shift 431
  1311.         *  shift 50
  1312.         &  shift 51
  1313.         .  reduce 29
  1314.  
  1315.         operator.function.ptr.opt  goto 637
  1316.         type.qualifier.list  goto 166
  1317.         pointer.operator  goto 429
  1318.         indirect.or.reference  goto 430
  1319.         type.qualifier  goto 46
  1320.  
  1321.  
  1322. 484: shift/reduce conflict (shift 50, red'n 103) on *
  1323. 484: shift/reduce conflict (shift 51, red'n 103) on &
  1324. state 484
  1325.         operator.new.type :  type.qualifier.list_operator.new.declarator.opt operator.new.initializer.opt
  1326.         type.qualifier.list :  type.qualifier.list_type.qualifier
  1327.         basic.type.specifier :  type.qualifier.list_basic.type.name
  1328.         sue.type.specifier :  type.qualifier.list_elaborated.type.name
  1329.         typedef.type.specifier :  type.qualifier.list_TYPEDEFname
  1330.         operator.new.declarator.opt : _    (103)
  1331.  
  1332.         DOUBLE  shift 42
  1333.         INT  shift 39
  1334.         STRUCT  shift 68
  1335.         LONG  shift 40
  1336.         ENUM  shift 66
  1337.         CHAR  shift 37
  1338.         UNION  shift 69
  1339.         CONST  shift 63
  1340.         FLOAT  shift 41
  1341.         SHORT  shift 38
  1342.         UNSIGNED  shift 44
  1343.         SIGNED  shift 43
  1344.         VOID  shift 36
  1345.         VOLATILE  shift 64
  1346.         CLASS  shift 70
  1347.         TYPEDEFname  shift 433
  1348.         *  shift 50
  1349.         &  shift 51
  1350.         [  shift 678
  1351.         .  reduce 103
  1352.  
  1353.         pointer.operator  goto 677
  1354.         indirect.or.reference  goto 676
  1355.         basic.type.name  goto 151
  1356.         operator.new.declarator.opt  goto 674
  1357.         operator.new.array.declarator  goto 675
  1358.         type.qualifier  goto 150
  1359.         elaborated.type.name  goto 152
  1360.         aggregate.name  goto 48
  1361.         enum.name  goto 49
  1362.         aggregate.key  goto 65
  1363.  
  1364.  
  1365. 485: shift/reduce conflict (shift 50, red'n 103) on *
  1366. 485: shift/reduce conflict (shift 51, red'n 103) on &
  1367. state 485
  1368.         operator.new.type :  type.specifier.or.name_operator.new.declarator.opt operator.new.initializer.opt
  1369.         operator.new.declarator.opt : _    (103)
  1370.  
  1371.         TYPEDEFname  shift 431
  1372.         *  shift 50
  1373.         &  shift 51
  1374.         [  shift 678
  1375.         .  reduce 103
  1376.  
  1377.         pointer.operator  goto 677
  1378.         indirect.or.reference  goto 676
  1379.         operator.new.declarator.opt  goto 679
  1380.         operator.new.array.declarator  goto 675
  1381.  
  1382.  
  1383. 642: reduce/reduce conflict (red'ns 17 and 22 ) on (
  1384. 642: reduce/reduce conflict (red'ns 17 and 22 ) on )
  1385. 642: reduce/reduce conflict (red'ns 17 and 22 ) on [
  1386. state 642
  1387.         paren.identifier.declarator :  rescoped.identifier_    (17)
  1388.         primary.expression :  rescoped.identifier_    (22)
  1389.  
  1390.         (  reduce 17
  1391.         )  reduce 17
  1392.         [  reduce 17
  1393.         .  reduce 22
  1394.  
  1395.  
  1396. 676: shift/reduce conflict (shift 50, red'n 103) on *
  1397. 676: shift/reduce conflict (shift 51, red'n 103) on &
  1398. state 676
  1399.         operator.new.declarator.opt :  indirect.or.reference_operator.new.declarator.opt
  1400.         pointer.operator :  indirect.or.reference_type.qualifier.list
  1401.         operator.new.declarator.opt : _    (103)
  1402.  
  1403.         CONST  shift 63
  1404.         VOLATILE  shift 64
  1405.         TYPEDEFname  shift 431
  1406.         *  shift 50
  1407.         &  shift 51
  1408.         [  shift 678
  1409.         .  reduce 103
  1410.  
  1411.         type.qualifier.list  goto 166
  1412.         pointer.operator  goto 677
  1413.         indirect.or.reference  goto 676
  1414.         operator.new.declarator.opt  goto 802
  1415.         operator.new.array.declarator  goto 675
  1416.         type.qualifier  goto 46
  1417.  
  1418.  
  1419. 677: shift/reduce conflict (shift 50, red'n 103) on *
  1420. 677: shift/reduce conflict (shift 51, red'n 103) on &
  1421. state 677
  1422.         operator.new.declarator.opt :  pointer.operator_operator.new.declarator.opt
  1423.         operator.new.declarator.opt : _    (103)
  1424.  
  1425.         TYPEDEFname  shift 431
  1426.         *  shift 50
  1427.         &  shift 51
  1428.         [  shift 678
  1429.         .  reduce 103
  1430.  
  1431.         pointer.operator  goto 677
  1432.         indirect.or.reference  goto 676
  1433.         operator.new.declarator.opt  goto 803
  1434.         operator.new.array.declarator  goto 675
  1435.  
  1436.  
  1437. 740: reduce/reduce conflict (red'ns 74 and 64 ) on )
  1438. 740: reduce/reduce conflict (red'ns 74 and 64 ) on ,
  1439. 740: reduce/reduce conflict (red'ns 74 and 64 ) on =
  1440. state 740
  1441.         postfix.expression :  TYPEDEFname ( )_    (74)
  1442.         parameter.type.list :  ( )_type.qualifier.list.opt
  1443.         type.qualifier.list.opt : _    (64)
  1444.  
  1445.         )  reduce 64
  1446.         ,  reduce 64
  1447.         CONST  shift 63
  1448.         VOLATILE  shift 64
  1449.         ELLIPSIS  reduce 64
  1450.         =  reduce 64
  1451.         .  reduce 74
  1452.  
  1453.         type.qualifier.list  goto 533
  1454.         type.qualifier.list.opt  goto 532
  1455.         type.qualifier  goto 46
  1456.  
  1457.  
  1458. 782: shift/reduce conflict (shift 595, red'n 418) on )
  1459. state 782
  1460.         class.rescoped.identifier :  TYPEDEFname_CLCL identifier.or.typedef.name
  1461.         class.rescoped.identifier :  TYPEDEFname_CLCL operator.function.name
  1462.         class.rescoped.identifier :  TYPEDEFname_CLCL ~ TYPEDEFname
  1463.         class.rescoped.identifier :  TYPEDEFname_CLCL class.rescoped.identifier
  1464.         postfix.expression :  TYPEDEFname_( )
  1465.         postfix.expression :  TYPEDEFname_( argument.expression.list )
  1466.         typedef.type.specifier :  TYPEDEFname_type.qualifier
  1467.         type.name :  TYPEDEFname_    (418)
  1468.         type.name :  TYPEDEFname_abstract.declarator
  1469.         paren.postfix.typedef.declarator :  ( TYPEDEFname_postfixing.abstract.declarator )
  1470.         simple.paren.typedef.declarator :  ( TYPEDEFname_)
  1471.         pointer.operator :  TYPEDEFname_CLCL * type.qualifier.list.opt
  1472.  
  1473.         (  shift 687
  1474.         )  shift 595
  1475.         CONST  shift 63
  1476.         VOLATILE  shift 64
  1477.         TYPEDEFname  shift 431
  1478.         CLCL  shift 129
  1479.         *  shift 50
  1480.         &  shift 51
  1481.         [  shift 98
  1482.         .  error
  1483.  
  1484.         pointer.operator  goto 684
  1485.         indirect.or.reference  goto 683
  1486.         postfixing.abstract.declarator  goto 874
  1487.         type.qualifier  goto 133
  1488.         parameter.type.list  goto 97
  1489.         abstract.declarator  goto 561
  1490.         unary.abstract.declarator  goto 548
  1491.         postfix.abstract.declarator  goto 549
  1492.         array.abstract.declarator  goto 96
  1493.  
  1494.  
  1495. 874: shift/reduce conflict (shift 838, red'n 591) on )
  1496. state 874
  1497.         paren.postfix.typedef.declarator :  ( TYPEDEFname postfixing.abstract.declarator_)
  1498.         abstract.declarator :  postfixing.abstract.declarator_    (591)
  1499.  
  1500.         )  shift 838
  1501.         .  error
  1502.  
  1503.  
  1504. 875: shift/reduce conflict (shift 840, red'n 418) on )
  1505. state 875
  1506.         class.rescoped.identifier :  TYPEDEFname_CLCL identifier.or.typedef.name
  1507.         class.rescoped.identifier :  TYPEDEFname_CLCL operator.function.name
  1508.         class.rescoped.identifier :  TYPEDEFname_CLCL ~ TYPEDEFname
  1509.         class.rescoped.identifier :  TYPEDEFname_CLCL class.rescoped.identifier
  1510.         postfix.expression :  TYPEDEFname_( )
  1511.         postfix.expression :  TYPEDEFname_( argument.expression.list )
  1512.         typedef.type.specifier :  TYPEDEFname_type.qualifier
  1513.         type.name :  TYPEDEFname_    (418)
  1514.         type.name :  TYPEDEFname_abstract.declarator
  1515.         paren.typedef.declarator :  indirect.or.reference ( TYPEDEFname_)
  1516.         paren.postfix.typedef.declarator :  ( TYPEDEFname_postfixing.abstract.declarator )
  1517.         pointer.operator :  TYPEDEFname_CLCL * type.qualifier.list.opt
  1518.  
  1519.         (  shift 687
  1520.         )  shift 840
  1521.         CONST  shift 63
  1522.         VOLATILE  shift 64
  1523.         TYPEDEFname  shift 431
  1524.         CLCL  shift 129
  1525.         *  shift 50
  1526.         &  shift 51
  1527.         [  shift 98
  1528.         .  error
  1529.  
  1530.         pointer.operator  goto 684
  1531.         indirect.or.reference  goto 683
  1532.         postfixing.abstract.declarator  goto 874
  1533.         type.qualifier  goto 133
  1534.         parameter.type.list  goto 97
  1535.         abstract.declarator  goto 561
  1536.         unary.abstract.declarator  goto 548
  1537.         postfix.abstract.declarator  goto 549
  1538.         array.abstract.declarator  goto 96
  1539.  
  1540.  
  1541. 876: shift/reduce conflict (shift 950, red'n 451) on ELSE
  1542. state 876
  1543.         selection.statement :  IF ( expression ) statement_    (451)
  1544.         selection.statement :  IF ( expression ) statement_ELSE statement
  1545.  
  1546.         ELSE  shift 950
  1547.         .  reduce 451
  1548.  
  1549.  
  1550. 1026: shift/reduce conflict (shift 1066, red'n 571) on ;
  1551. state 1026
  1552.         constructor.conflicting.parameter.list.and.body :  ( TYPEDEFname )_;
  1553.         constructor.conflicting.parameter.list.and.body :  ( TYPEDEFname )_type.qualifier.list ;
  1554.         constructor.conflicting.parameter.list.and.body :  ( TYPEDEFname )_constructor.init.list.opt compound.statement
  1555.         constructor.conflicting.parameter.list.and.body :  ( TYPEDEFname )_type.qualifier.list constructor.init.list.opt compound.statement
  1556.         simple.paren.typedef.declarator :  ( TYPEDEFname )_    (571)
  1557.         constructor.init.list.opt : _    (539)
  1558.  
  1559.         CONST  shift 63
  1560.         VOLATILE  shift 64
  1561.         :  shift 81
  1562.         ;  shift 1066
  1563.         {  reduce 539
  1564.         .  reduce 571
  1565.  
  1566.         type.qualifier.list  goto 1067
  1567.         type.qualifier  goto 46
  1568.         constructor.init.list  goto 1069
  1569.         constructor.init.list.opt  goto 1068
  1570.  
  1571.  
  1572. 1065: shift/reduce conflict (shift 1102, red'n 359) on ;
  1573. state 1065
  1574.         member.conflict.paren.postfix.declaring.item :  TYPEDEFname ( TYPEDEFname postfixing.abstract.declarator )_member.pure.opt
  1575.         constructor.conflicting.typedef.declarator :  ( TYPEDEFname postfixing.abstract.declarator )_type.qualifier.list ;
  1576.         constructor.conflicting.typedef.declarator :  ( TYPEDEFname postfixing.abstract.declarator )_type.qualifier.list constructor.init.list.opt compound.statement
  1577.         constructor.conflicting.typedef.declarator :  ( TYPEDEFname postfixing.abstract.declarator )_;
  1578.         constructor.conflicting.typedef.declarator :  ( TYPEDEFname postfixing.abstract.declarator )_constructor.init.list.opt compound.statement
  1579.         member.pure.opt : _    (359)
  1580.         constructor.init.list.opt : _    (539)
  1581.  
  1582.         CONST  shift 63
  1583.         VOLATILE  shift 64
  1584.         :  shift 81
  1585.         =  shift 971
  1586.         ;  shift 1102
  1587.         {  reduce 539
  1588.         .  reduce 359
  1589.  
  1590.         type.qualifier.list  goto 1101
  1591.         type.qualifier  goto 46
  1592.         member.pure.opt  goto 1100
  1593.         constructor.init.list  goto 1069
  1594.         constructor.init.list.opt  goto 1103
  1595.  
  1596.  
  1597. 1089: shift/reduce conflict (shift 1102, red'n 359) on ;
  1598. state 1089
  1599.         member.conflict.paren.postfix.declaring.item :  declaration.specifier ( TYPEDEFname postfixing.abstract.declarator )_member.pure.opt
  1600.         constructor.conflicting.typedef.declarator :  ( TYPEDEFname postfixing.abstract.declarator )_type.qualifier.list ;
  1601.         constructor.conflicting.typedef.declarator :  ( TYPEDEFname postfixing.abstract.declarator )_type.qualifier.list constructor.init.list.opt compound.statement
  1602.         constructor.conflicting.typedef.declarator :  ( TYPEDEFname postfixing.abstract.declarator )_;
  1603.         constructor.conflicting.typedef.declarator :  ( TYPEDEFname postfixing.abstract.declarator )_constructor.init.list.opt compound.statement
  1604.         member.pure.opt : _    (359)
  1605.         constructor.init.list.opt : _    (539)
  1606.  
  1607.         CONST  shift 63
  1608.         VOLATILE  shift 64
  1609.         :  shift 81
  1610.         =  shift 971
  1611.         ;  shift 1102
  1612.         {  reduce 539
  1613.         .  reduce 359
  1614.  
  1615.         type.qualifier.list  goto 1101
  1616.         type.qualifier  goto 46
  1617.         member.pure.opt  goto 1128
  1618.         constructor.init.list  goto 1069
  1619.         constructor.init.list.opt  goto 1103
  1620.  
  1621.  
  1622. 123/127 terminals, 160/200 nonterminals
  1623. 609/650 grammar rules, 1157/1200 states
  1624. 25 shift/reduce, 7 reduce/reduce conflicts reported
  1625. 243/350 working sets used
  1626. memory: states,etc. 13727/60000, parser 10871/12000
  1627. 495/600 distinct lookahead sets
  1628. 756 extra closures
  1629. 7300 shift entries, 25 exceptions
  1630. 1797 goto entries
  1631. 4731 entries saved by goto default
  1632. Optimizer space used: input 18036/60000, output 8092/12000
  1633. 8092 table entries, 3568 zero
  1634. maximum spread: 351, maximum offset: 1148
  1635.